package com.neuralnoise;

import java.util.Collection;
import java.util.LinkedList;
import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.criterion.Restrictions;

import com.neuralnoise.hibernate.HibernateSessionFactory;
import com.neuralnoise.hibernate.facebook.FacebookType;
import com.neuralnoise.hibernate.facebook.FacebookTypeDAO;
import com.neuralnoise.hibernate.facebook.Profile;
import com.neuralnoise.hibernate.facebook.ProfileDAO;
import com.neuralnoise.hibernate.facebook.User;
import com.neuralnoise.hibernate.facebook.UserDAO;
import com.neuralnoise.hibernate.facebook.UserTypeRelationship;
import com.neuralnoise.hibernate.facebook.UserTypeRelationshipDAO;
import com.neuralnoise.hibernate.facebook.UserTypeRelationshipId;

public class FacebookDB extends AbstractDB {

	private Logger logger = Logger.getLogger(this.getClass());
	
	private FacebookDB() { }
	
	public static void clean() {
		HibernateSessionFactory.getSession().beginTransaction();
		UserDAO udao = new UserDAO();
		List<User> users = udao.findAll();
		for (User user : users) {
			udao.delete(user);
		}
		FacebookTypeDAO ftdao = new FacebookTypeDAO();
		List<FacebookType> fts = ftdao.findAll();
		for (FacebookType ft : fts) {
			ftdao.delete(ft);
		}
		HibernateSessionFactory.getSession().getTransaction().commit();
	}

	public static User getUser(String id) {
		HibernateSessionFactory.getSession().beginTransaction();
		UserDAO jdao = new UserDAO();
		User User = jdao.findById(id);
		HibernateSessionFactory.getSession().getTransaction().commit();
		return User;
	}
	
	public static Collection<User> getUsers() {
		HibernateSessionFactory.getSession().beginTransaction();
		UserDAO jdao = new UserDAO();
		List<User> Users = jdao.findAll();
		HibernateSessionFactory.getSession().getTransaction().commit();
		return Users;
	}
	
	public static User addUser(String id) {
		HibernateSessionFactory.getSession().beginTransaction();
		UserDAO jdao = new UserDAO();
		User User = new User(id);
		jdao.merge(User);
		HibernateSessionFactory.getSession().getTransaction().commit();
		return User;
	}
	
	public static void delUser(String id) {
		HibernateSessionFactory.getSession().beginTransaction();
		UserDAO jdao = new UserDAO();
		User j = jdao.findById(id);
		if (j != null) {
			jdao.delete(j);
		}
		HibernateSessionFactory.getSession().getTransaction().commit();
	}
	
	public static User toUser(String id) {
		HibernateSessionFactory.getSession().beginTransaction();
		UserDAO jdao = new UserDAO();
		User user = jdao.findById(id);
		if (user == null) {
			user = new User(id);
			jdao.merge(user);
		}
		HibernateSessionFactory.getSession().getTransaction().commit();
		return user;
	}
	
	public static FacebookType toFacebookType(String id) {
		HibernateSessionFactory.getSession().beginTransaction();
		FacebookTypeDAO jdao = new FacebookTypeDAO();
		FacebookType ft = jdao.findById(id);
		if (ft == null) {
			ft = new FacebookType(id);
			jdao.merge(ft);
		}
		HibernateSessionFactory.getSession().getTransaction().commit();
		return ft;
	}
	
	public static Profile getProfile(String user) {
		HibernateSessionFactory.getSession().beginTransaction();
		ProfileDAO pdao = new ProfileDAO();
		Profile profile = pdao.findById(user);
		HibernateSessionFactory.getSession().getTransaction().commit();
		return profile;
	}
	
	public static Collection<Profile> getProfiles() {
		HibernateSessionFactory.getSession().beginTransaction();
		ProfileDAO pdao = new ProfileDAO();
		Collection<Profile> profiles = pdao.findAll();
		HibernateSessionFactory.getSession().getTransaction().commit();
		return profiles;
	}
	
	public static void addProfile(String id, String name, String firstName, String lastName, String link,
			String userName, String gender, String locale, String website) {
		HibernateSessionFactory.getSession().beginTransaction();
		ProfileDAO pdao = new ProfileDAO();
		// user, name, firstName, lastName, link, userName, gender, locale, website
		Profile p = new Profile(id, name, firstName, lastName, link, userName, gender, locale, website);
		pdao.merge(p);
		HibernateSessionFactory.getSession().getTransaction().commit();
	}

	
	public static void addProfile(String id, com.restfb.types.User user) {
		HibernateSessionFactory.getSession().beginTransaction();
		ProfileDAO pdao = new ProfileDAO();
		// user id, name, firstName, lastName, link, userName, gender, locale, website
		Profile p = new Profile(id, user.getName(), user.getFirstName(), user.getLastName(), user.getLink(),
				user.getUsername(), user.getGender(), user.getLocale(), user.getWebsite());
		pdao.merge(p);
		HibernateSessionFactory.getSession().getTransaction().commit();
	}
	
	public static FacebookType getFacebookType(String id) {
		HibernateSessionFactory.getSession().beginTransaction();
		FacebookTypeDAO ftdao = new FacebookTypeDAO();
		FacebookType ft = ftdao.findById(id);
		HibernateSessionFactory.getSession().getTransaction().commit();
		return ft;
	}
	
	public static FacebookType addFacebookType(String id, String name) {
		HibernateSessionFactory.getSession().beginTransaction();
		FacebookTypeDAO ftdao = new FacebookTypeDAO();
		FacebookType ft = new FacebookType(id, name);
		ftdao.merge(ft);
		HibernateSessionFactory.getSession().getTransaction().commit();
		return ft;
	}
	
	public static Collection<UserTypeRelationship> getFacebookTypeRelationships(String user) {
		HibernateSessionFactory.getSession().beginTransaction();
		UserTypeRelationshipDAO pdao = new UserTypeRelationshipDAO();
		Collection<UserTypeRelationship> types = pdao.findByProperty("id.user.id", user);
		HibernateSessionFactory.getSession().getTransaction().commit();
		return types;
	}
	
	public static UserTypeRelationship addFacebookTypeRelationship(String _user, String _facebookType,
			UserTypeRelationshipId.RelationType type) {
		HibernateSessionFactory.getSession().beginTransaction();
		UserDAO udao = new UserDAO();
		FacebookTypeDAO fdao = new FacebookTypeDAO();
		User user = udao.findById(_user);
		FacebookType facebookType = fdao.findById(_facebookType);
		UserTypeRelationshipDAO utrdao = new UserTypeRelationshipDAO();
		UserTypeRelationshipId id = new UserTypeRelationshipId(type, user, facebookType);
		UserTypeRelationship utr = new UserTypeRelationship(id);
		utrdao.merge(utr);
		HibernateSessionFactory.getSession().getTransaction().commit();
		return utr;
	}
	
	public static Collection<User> getFriendsOf(String id) {
		HibernateSessionFactory.getSession().beginTransaction();
		Criteria criteria = HibernateSessionFactory.getSession().createCriteria(User.class);
		criteria = criteria.createAlias("usersForSubject", "friendsOf");
		criteria = criteria.add(Restrictions.eq("friendsOf.id", id));
		Collection<User> friends = criteria.list();
		HibernateSessionFactory.getSession().getTransaction().commit();
		return friends;
	}
	
	public static Collection<User> addFriendsOf(String id, Collection<String> friends) {
		User User = toUser(id);
		Collection<User> ufriends = new LinkedList<User>();
		for (String friend : friends) {
			ufriends.add(toUser(friend));
		}
		HibernateSessionFactory.getSession().beginTransaction();
		UserDAO udao = new UserDAO();
		for (User ufriend : ufriends) {
			User.getUsersForObject().add(ufriend);
			udao.merge(User);
		}
		HibernateSessionFactory.getSession().getTransaction().commit();
		return ufriends;
	}
	
	public static User addFriendOf(String id, String friend) {
		User User = toUser(id);
		User ufriend = toUser(friend);
		HibernateSessionFactory.getSession().beginTransaction();
		UserDAO udao = new UserDAO();
		User.getUsersForObject().add(ufriend);
		udao.merge(User);
		HibernateSessionFactory.getSession().getTransaction().commit();
		return ufriend;
	}
}
